package com.tsfyun.scm.config;

import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Maps;
import com.tsfyun.common.base.config.properties.NoticeProperties;
import com.tsfyun.common.base.dto.TaskDTO;
import com.tsfyun.common.base.enums.domain.DomainTypeEnum;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.help.DingTalkNoticeUtil;
import com.tsfyun.common.base.security.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Objects;

/**
 * @Description: 防止changeDocumentStatus与实际传入单据不匹配调增加切面验证
 * @CreateDate: Created in 2021/10/19 17:03
 */
@Aspect
@Order(-8)
@Component
@Slf4j
public class DomainTaskAspect {

    private final String point = "execution(* com.tsfyun.*.service..*.*(..))&& args(com.tsfyun.common.base.dto.TaskDTO)";

    @Autowired
    private NoticeProperties noticeProperties;

    //ServiceImpl类对应的domainClass
    private static Map<String,String> INVOKE_DOMAIN_MAP = Maps.newHashMap();

    @Around(point)
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        Object[] args = pjp.getArgs();
        Class clazz = pjp.getSignature().getDeclaringType();
        if(args != null && args.length > 0) {
            Object requestParam = args[0];
            if(requestParam instanceof TaskDTO) {
                TaskDTO taskDTO = (TaskDTO)requestParam;
                String domainClass = taskDTO.getDocumentClass();
                DomainTypeEnum domainTypeEnum = DomainTypeEnum.of(domainClass);
                String superClazzName = clazz.getSuperclass().getSimpleName();
                String genericSuperTypeName = clazz.getGenericSuperclass().getTypeName();
                if(Objects.nonNull(domainTypeEnum)
                        && Objects.equals(superClazzName,"ServiceImpl")){
                    String invokeDomain = INVOKE_DOMAIN_MAP.computeIfAbsent(genericSuperTypeName,k->{
                        Type genericSuperclass = clazz.getGenericSuperclass();
                        if(genericSuperclass instanceof ParameterizedType) {
                            return ((Class) ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0]).getSimpleName();
                        }
                        return null;
                    });
                    if(!Objects.equals(invokeDomain,domainTypeEnum.getCode())) {
                        DingTalkNoticeUtil.send2DingDingOtherException("非法请求处理单据任务", StrUtil.format("非法请求处理单据任务，操作人【{}/{}】", SecurityUtil.getCurrentPersonId(),SecurityUtil.getCurrentPersonName()),null,noticeProperties.getDingdingUrl());
                        throw new ServiceException("非法操作，请勿使用非法工具，否则后续将无法使用本系统");
                    }
                }
            }
        }
        Object result = pjp.proceed();
        return result;
    }

}
